/**********************************************************************************************************************
 *
 * Project:    mGameEngine
 * File:       ms3dloader.h
 * Author:     karooolek
 * Created on: 2009-03-25
 *
 **********************************************************************************************************************/

#ifndef MS3DLOADER_H_
#define MS3DLOADER_H_

#include "meshloader.h"
#include "material.h"
#include "imageloader.h"
#include "texturedmaterial.h"

// disable structure fields alignment
#if !(defined(lint) || defined(RC_INVOKED))
#   if( _MSC_VER >= 800 && !defined(_M_I86)) || defined(_PUSHPOP_SUPPORTED)
#       pragma warning(disable:4103)
#       if !defined( MIDL_PASS ) || defined( __midl )
#           pragma pack(push, 1)
#       else
#           pragma pack(1)
#       endif
#   else
#       pragma pack(1)
#   endif
#endif

namespace mGameEngine
{
namespace Graphics
{

/**
 * MS3D mesh file loader.
 */
class MS3DLoader : public MeshLoader
{
private:
    // ms3d file structures
    struct MS3DHeader
    {
        char id[10];                             // always "MS3D000000"
        int version;                             // 4
    };

    struct MS3DVertex
    {
        uint8 flags;                             // SELECTED | SELECTED2 | HIDDEN
        float vertex[3];                         //
        char boneId;                             // -1 = no bone
        uint8 referenceCount;                    //
    };

    struct MS3DTriangle
    {
        uint16 flags;                            // SELECTED | SELECTED2 | HIDDEN
        uint16 vertexIndices[3];                 //
        float vertexNormals[3][3];               //
        float s[3];                              //
        float t[3];                              //
        uint8 smoothingGroup;                    // 1 - 32
        uint8 groupIndex;                        //
    };

    struct MS3DEdge
    {
        uint16 edgeIndices[2];                   //
    };

    struct MS3DGroup
    {
        uint8 flags;                             // SELECTED | HIDDEN
        char name[32];                           //
        uint16 numtriangles;                     //
        uint16* triangleIndices;                 // the groups group the triangles
        char materialIndex;                      // -1 = no material
    };

    struct MS3DMaterial
    {
        char name[32];                           //
        float ambient[4];                        //
        float diffuse[4];                        //
        float specular[4];                       //
        float emissive[4];                       //
        float shininess;                         // 0.0f - 128.0f
        float transparency;                      // 0.0f - 1.0f
        char mode;                               // 0, 1, 2 is unused now
        char texture[128];                       // texture.bmp
        char alphamap[128];                      // alpha.bmp
    };

    struct MS3DKeyframeOrientation
    {
        float time;                              // time in seconds
        float rotation[3];                       // x, y, z angles
    };

    struct MS3DKeyframePosition
    {
        float time;                              // time in seconds
        float position[3];                       // local position
    };

    struct MS3DJoint
    {
        uint8 flags;                             // SELECTED | DIRTY
        char name[32];                           //
        char parentName[32];                     //
        float rotation[3];                       // local reference matrix
        float position[3];                       //
        uint16 numKeyFramesRot;                  //
        uint16 numKeyFramesTrans;                //
        MS3DKeyframeOrientation* keyFramesRot;   // local animation matrices
        MS3DKeyframePosition* keyFramesTrans;    // local animation matrices
    };

public:
    /**
     * Create MS3D mesh loader with no file name specified.
     */
    MS3DLoader();

    /**
     * Create MS3D mesh file loader with specified file name.
     * @param filename MS3D mesh file name to load
     */
    MS3DLoader(const String &filename);

    /**
     * Destroy MS3D mesh file loader.
     */
    ~MS3DLoader();

    /**
     * Load mesh from MS3D file.
     */
    void load();
};

}
}

#endif // MS3DLOADER_H_
